export class E_WebSocket {
    // websocket
    private everWebSocket: WebSocket | undefined
    // websocket 地址
    private url = ''
    // 心跳检测频率 单位：秒
    private timer = 60
    // 是否开启心跳检测
    private reconnect = true
    // 心跳检测 定时器
    private heartInterval: any
    // 重连 延时器
    private reconnectTimeout: any
    // 重连 状态
    private lockReconnect = false

    // 打开时候的回调
    private openFn: ((e: any) => void) | undefined
    // 消息接收回调
    private onMessageFn: ((data: any, e: any) => void) | undefined
    // 关闭回调
    private onCloseFn: ((e: any) => void) | undefined
    // 异常回调
    private onErrorFn: ((e: any) => void) | undefined

    constructor(param: E_WebSocketParam | string) {
        if (typeof param === 'object') {
            this.reconnect = param.reconnect ?? true
            this.timer = param.timer ?? 60
        }
        this.url = this.handleUrl(param)

        return this.init()
    }

    private handleUrl(param: E_WebSocketParam | string) {
        let url = typeof param == 'string' ? param : param.url
        const env = import.meta.env
        if (url.startsWith('/')) {
            url = url.slice(1)
        }
        url = url.startsWith('ws')
            ? url
            : `${env.VITE_APP_BEG_WS}://${env.VITE_PROXY_DOMAIN_REAL_WS}/${url}`
        return url
    }

    private init() {
        this.everWebSocket = new WebSocket(this.url)
        // 用于指定连接成功后的回调函数。
        this.everWebSocket.onopen = (e: any) => {
            // 打开 心跳检测
            if (this.reconnect && this.timer > 0) {
                this.heartCheck()
            }
            this.openFn && this.openFn(e)
        }

        // 用于指定当从服务器接受到信息时的回调函数。
        this.everWebSocket.onmessage = (e: any) => {
            this.onMessageFn && this.onMessageFn(e.data, e)
        }
        // 用于指定连接关闭后的回调函数。
        this.everWebSocket.onclose = (e: any) => {
            this.onCloseFn && this.onCloseFn(e)
        }
        // 用于指定连接失败后的回调函数。
        this.everWebSocket.onerror = e => {
            // 关闭心跳检测
            clearInterval(this.heartInterval)
            this.handleReconnect()
            this.onErrorFn && this.onErrorFn(e)
        }
        return this
    }

    // 心跳检测
    private heartCheck() {
        this.heartInterval = setInterval(() => {
            this.everWebSocket?.send('type:ping')
        }, this.timer * 1000)
    }

    // 重连
    private handleReconnect() {
        if (this.lockReconnect) {
            return
        }

        this.lockReconnect = true
        this.reconnectTimeout && clearTimeout(this.reconnectTimeout)
        this.reconnectTimeout = setTimeout(() => {
            this.init()
            this.lockReconnect = false
        }, 5000)
    }
    // 打开时的回调
    public onOpen(fn: (e: any) => void) {
        if (typeof fn == 'function') {
            this.openFn = fn
        } else {
            this.openFn = () => {}
        }
        return this
    }
    // 消息接收时回调
    public onMessage(fn: (data: any, e: any) => void) {
        if (typeof fn == 'function') {
            this.onMessageFn = fn
        } else {
            this.onMessageFn = () => {}
        }
        return this
    }
    // 关闭后的回调
    public onClose(fn: (e: any) => void) {
        if (typeof fn == 'function') {
            this.onCloseFn = fn
        } else {
            this.onCloseFn = () => {}
        }
        return this
    }
    // 异常时的回调
    public onError(fn: (e: any) => void) {
        if (typeof fn == 'function') {
            this.onErrorFn = fn
        } else {
            this.onErrorFn = () => {}
        }
        return this
    }
    // 关闭连接
    public close() {
        // 关闭心跳检测
        clearInterval(this.heartInterval)
        // 关闭 重连
        clearTimeout(this.reconnectTimeout)
        this.everWebSocket?.close()
    }
}

export interface E_WebSocketParam {
    reconnect?: boolean // 是否启用断线重连
    timer?: number // 心跳检测周期
    url: string // webSocket 地址
}
